import glob
import hashlib
import sqlite3
import os
import time
import re


import sys, getopt

def main(argv):
    directory=''
    exclude=''
    savedb=''
    helps='''用法:filesmd5.py [选项]
        -h,--help  显示帮助信息
        -s,--savedb sqlite数据库地址路径,如/home/web/files.db
        -d,--directory  目标路径,用来校验的目录名字，绝对路径/home/web/domain_com
        -e,--exclude    排除的目录,多个目录用逗号分割,如/home/web/domain_com/runtime,/home/web/158_com/theme
        '''
    try:
        opts, args = getopt.getopt(argv,"hs:d:e:",["savedb=","directory=","exclude="])
    except getopt.GetoptError:
        print('filesmd5.py -s </home/files.db> -d </home/web/foo> -e </home/web/foo/bar,/home/web/foo/bar2>')
        sys.exit(2)
    for opt, arg in opts:
        if opt == '-h':
            print(helps)
            sys.exit()
        elif opt in ("-d", "--directory"):
            directory = arg
        if opt in ("-e", "--exclude"):
            exclude = arg
        if opt in ('-s',"--savedb"):
            savedb = arg
    return directory,exclude,savedb


def get_conn(path):
    
    if os.path.exists(path) and os.path.isfile(path):
        c = sqlite3.connect(path)
        return c
    else:
        c = sqlite3.connect(path)
        c.cursor()
        c.execute('''CREATE TABLE FILES(
              FILEPATH TEXT PRIMARY KEY NOT NULL,
              md5sum TEXT NOT NULL,
              DATE TM NOT NULL)''')
        return c
    print('Opend database successfully')

def get_cursor(conn):
    if conn is not None:
        return conn.cursor()
    else:
        return get_conn('').cursor()
# conn.close()

#CURD操作
#@author jjger
#@conn database
#@param data [('/home/web/xxx',md5sum,date),(),()]
def save(conn,data):
    # if sql is not None:
    if data is not None:
        for i in data:
            # print(str(i))
            sql = "INSERT INTO FILES VALUES " + str(i)
            print(sql)
            # return(str(i))
            cu = get_cursor(conn)
            cu.execute(sql)
            conn.commit()


def upfileinfo(conn,data):
    # if sql is not None:
    if data is not None:
        for i in data:
            # 这里的i变成了字符串，需要提出小括号，并拆分成数组
            print(i)
            i = i.strip("()").replace("'",'').split(",")
            print(i)
            sql = "UPDATE FILES set md5sum = '"+ i[1].strip(' ') + "',date = '" + i[2].strip(' ') + "' where filepath = '" + str(i[0]) + "'"
            # return(str(i))
            cu = get_cursor(conn)
            cu.execute(sql)
            conn.commit()
            
            
            
#@author jjger
#@param conn database
#@data [('/home/web/xxx',md5sum,date),(),()]
#@return no
def fetchone(conn,data):
    if data is not None:
        for i in data:
            # i like ('/home/web/xxx',md5sum,date)
            
            sql_filename = "select * from files where FILEPATH = '" + str(i[0]) + "'"
            sql_md5sum = "select * from files where FILEPATH = '" + str(i[0]) + "' and md5sum = '" + str(i[1]) +"'"
            # sql = "select * from files where FILEPATH = '111.php'"
            cu = get_cursor(conn)
            cu.execute(sql_filename)
            # print(type(rows.fetchall))
            result=cu.fetchone()
            if result is None:
                # print(data)
                #把result转换为save函数需要的data类型，也就是list
                #如果结果集查询是空的，则把此文件的校验信息插入数据库中
                lstr=list()
                lstr.append(str(i))
                save(conn,lstr)
                print("新增了文件：{0}" .format(str(i[0])))
            else:
                #判断校验值是否相等，如果不相等，则打印文件校验失败
                #同时把文件的校验值更新到数据库中
                cu.execute(sql_md5sum)
                result_md5sum = cu.fetchone()
                if result_md5sum is None:
                    print("文件在{0}被修改过了：{1}" .format(str(i[2]),str(i[0])))
                    lstr=list()
                    lstr.append(str(i))
                    upfileinfo(conn,lstr)
                # print(result[0])
                #return result[0]
                # print(1111111)
            



# get_data()
# @param path files Path,如/home/web/xxx
# @param fype 文件类型,如php
# return list 拼接好的要插入数据库中的数据list
def get_data(path,ftype):
    files = glob.glob(path + "/*." + ftype)
    data=[]
    for testfile in files:
        myhash = hashlib.md5()
        f = open(testfile,'rb')
        while True:
            b = f.read(8096)
            if not b:
                break
            myhash.update(b)
        f.close()
        data.append((testfile,myhash.hexdigest(),time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())))
    return data

#遍历目录，得到文件，并从数据库中查询文件名
#@param $objectpath directory path
#@return list   ['/home/web/abc_com/aaa.php',md5sum,date]
def get_filesinfo(objectpath):
    for d,dirs,fs in os.walk(objectpath):
        # print(d)
        data = get_data(d,'php') #遍历文件后，得到一个[文件路径,md5值,日期]的列表
        # print(data)
        save(conn,data)
    stats=fetchone(conn,data) #把得到的文件送入数据库查询，
    print(stats)
    
def get_files_status(objectpath):
    #遍历目录,为后续遍历目录中的文件做准备
    for d,dirs,fs in os.walk(objectpath):
        #通过正则判断是否有需要排除的目录，匹配则跳过循环,跳过匹配的目录
        ctn=0
        for exclude in excludedir:
            if re.search(exclude,d):
                ctn=1
                continue
        if ctn:
            continue
        # print(d)
        data = get_data(d,'php') #遍历文件后，得到一个[文件路径,md5值,日期]的列表
        # print(data)
        # save(conn,data)
        stats=fetchone(conn,data) #把得到的文件送入数据库查询，


if __name__ == "__main__":
    vars = main(sys.argv[1:])
    # print(vars)

directory = vars[0]
excludedir= vars[1].split(",")
savedb = vars[2]
if savedb.strip() == '':
    savedb = directory/files.db
# print(excludedir[0].split(","))
#
# print(type(excludedir))
# print(excludedir[0])
# print(directory)
# print(excludedir)
# print(savedb)

# exit()
# excludedir=['/home/web/158_com/runtime_backup','/home/web/158_com/theme']
conn = get_conn(savedb)
get_files_status(directory)
